<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../js/vue.js"></script>
</head>

<body>
    <div id="app">
        <p class="one" ref="one">{{count}}</p>
        <p class="two">{{double()}}</p>
        <p class="three">{{triple}}</p>
        <p>
            <button @click="count++">点击</button>
        </p>
        <p>
            <button @click="$destroy()">卸载Vue实例</button>
        </p>
    </div>
</body>
<script>

    // Vue特征
    // 1. 声明式渲染(Vue实例Vue初始化)
    // 2. 响应式(Vue实例数据更新)

    // 生命周期分为三个阶段: 初始化阶段  更新阶段  销毁阶段   8个钩子函数

    // 初始化阶段
    // beforeCreate
    // 第一个生命周期钩子函数,发生在Vue实例创建之后, 进行数据侦听(data)和事件/侦听器(watch)的配置之前同步调用,此时Vue实例选项(new Vue(options))配置之前

    // created
    // 在实例创建完成后被立即同步调用。在这一步中，实例已完成对选项的处理，意味着以下内容已被配置完毕：数据侦听、计算属性、方法、事件 / 侦听器的回调函数。然而，挂载阶段还没开始，且 $el property 目前尚不可用。

    // beforeMount
    // 在挂载开始之前被调用：相关的 render 函数首次被调用。 通过render()函数将模板编译为vDom (虚拟DOM), 此时还未渲染真实DOM


    // mounted
    // 实例被挂载后调用，这时 el 被新创建的 vm.$el 替换了。如果根实例挂载到了一个文档内的元素上，当 mounted 被调用时 vm.$el 也在文档内。
    // vDom  解析为真实DOM 渲染到挂载的元素中

    // !!!!!!!!!!
    // 注意 mounted 不会保证所有的子组件也都被挂载完成。如果你希望等到整个视图都渲染完毕再执行某些操作，可以在 mounted 内部使用 vm.$nextTick：

    // 更新阶段
    // beforeUpdate
    // 在数据发生改变后，DOM 被更新之前被调用。这里适合在现有 DOM 将要被更新之前访问它，比如移除手动添加的事件监听器。

    // updated
    // 在数据更改导致的虚拟 DOM 重新渲染和更新完毕之后被调用。
    // 当这个钩子被调用时，组件 DOM 已经更新，所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下，你应该避免在此期间更改状态。如果要相应状态改变，通常最好使用计算属性或 watcher 取而代之。
    // 不建议在此阶段修改数据  =>  导致视图递归渲染

    // !!!!!!!!
    // 注意，updated 不会保证所有的子组件也都被重新渲染完毕。如果你希望等到整个视图都渲染完毕，可以在 updated 里使用 vm.$nextTick：

    // 销毁阶段
    // beforeDestroy
    // 实例销毁之前调用。在这一步，实例仍然完全可用。 => 一般习惯在此阶段清除绑定的事件,监听器,计时器,延时器

    // destroyed
    // 实例销毁后调用。该钩子被调用后，对应 Vue 实例的所有指令都被解绑，所有的事件监听器被移除，所有的子实例也都被销毁。  => Vue实例不在工作了

    var vm = new Vue({
        el: "#app",
        data: {
            count: 1,
        },
        methods: {
            double: function () {
                console.log("double被调用");
                return this.count * 2;
            }
        },
        computed: {
            triple: function () {
                console.log("triple被调用");
                return this.count * 3;
            },
        },
        watch: {
            count: function (newVal, oldVal) {
                console.log("监听到count改变", newVal, oldVal);
            }
        },
        // beforeCreate: function () {
        //     console.log("1. beforeCreate 实例", this);
        //     console.log("1. beforeCreate 数据", this.$data, this.count);
        //     console.log("1. beforeCreate 方法", this.double);
        //     console.log("1. beforeCreate 计算属性", this.triple);
        //     console.log("1. beforeCreate $el", this.$el);
        // },
        // created: function () {
        //     // new Vue(options) 选项已经配置完毕
        //     console.log("2. created 实例", this);
        //     console.log("2. created 数据", this.$data, this.count);
        //     console.log("2. created 方法", this.double);
        //     console.log("2. created 计算属性", this.triple);
        //     console.log("2. created $el", this.$el);
        // },
        // beforeMount: function () {
        //     console.log("3.beforeMount 实例", this);
        //     console.log("3.beforeMount 数据", this.$data, this.count);
        //     console.log("3.beforeMount 方法", this.double);
        //     console.log("3.beforeMount 计算属性", this.triple);
        //     var one = document.getElementsByClassName("one")[0];
        //     console.log("3.beforeMount 模板", one);
        //     console.log("3.beforeMount $el", this.$el);
        // },
        // mounted() {
        //     console.log("4.mounted 实例", this);
        //     console.log("4.mounted 数据", this.$data, this.count);
        //     console.log("4.mounted 方法", this.double);
        //     console.log("4.mounted 计算属性", this.triple);
        //     var one = document.getElementsByClassName("one")[0];
        //     console.log("4.mounted 模板", one);
        //     console.log("4.mounted $el", this.$el);
        //     console.log("4.mounted $refs", this.$refs);
        // },

        // -------------------------更新阶段-----------------------------------
        // beforeUpdate: function () {
        //     console.log("5. beforeUpdate 实例", this);
        //     console.log("5. beforeUpdate 数据", this.count);
        //     console.log("5. beforeUpdate 视图", this.$refs.one.textContent);
        // },
        // updated: function () {
        //     console.log("6. updated 实例", this);
        //     console.log("6. updated 数据", this.count);
        //     console.log("6. updated 视图", this.$refs.one.textContent);
        // },


        // --------------------------销毁阶段-----------------------------------
        beforeDestroy: function () {
            console.log("7. beforeDestroy 实例", this);
            console.log("7. beforeDestroy 数据", this.count);
            console.log("7. beforeDestroy 方法", this.double);
            console.log("7. beforeDestroy 计算属性", this.triple);
            console.log("7. beforeDestroy 视图", this.$refs.one.textContent);
        },
        destroyed: function () {
            console.log("8. destroyed 实例", this);
            console.log("8. destroyed 数据", this.count);
            console.log("8. destroyed 方法", this.double);
            console.log("8. destroyed 计算属性", this.triple);
            console.log("8. destroyed $el", this.$el);
            console.log("8. destroyed $refs", this.$refs);
        },
    })



</script>

</html>